#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include "Thread.hpp"
#include "LockGuard.hpp"

//线程池的线程数量
const int gmax = 3;

template <class T>
class ThreadPool;

//这个类主要是方便将线程的名字拿上来，以供让我知道是哪一个线程执行的这个任务
//如果不使用任可以运行，但是不知道是哪一个线程执行的任务
template <class T>
class ThreadData
{
public:
    ThreadPool<T> *_threadpool;
    std::string _name;

public:
    ThreadData(ThreadPool<T> *threadpool, std::string name)
        : _threadpool(threadpool), _name(name)
    {}
};//ThreadData end

template <class T>
class ThreadPool
{
private:
        //线程从队列中拿取任务
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

    // 线程要执行操作
    //由于要使用ThreadPool中的类内成员，所以args必须是ThreadPoll类型的指针或者包含该指针的结构
    static void *handTask(void *args)
    {
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            T t;
            {
                //使用的是RAII风格的锁，出了作用域自动解锁
                LockGuard lockguard(&td->_threadpool->_mutex);
                while (td->_threadpool->_task_queue.empty())
                {
                    pthread_cond_wait(&td->_threadpool->_cond, &td->_threadpool->_mutex);
                }
            }
            t = td->_threadpool->pop();
            std::cout << td->_name << " : " << t.toTaskString() << "; 完成，结果是: "<< t() << std::endl;
        }
        delete td;
    }

public:
    ThreadPool(int num = gmax) : _num(num)
    {
        for (int i = 0; i < _num; i++)
        {
            //这里仅仅只是创建_num个Thread对象
            _threads.push_back(new Thread(i + 1));
        }

        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    //创建并启动线程
    void run()
    {
        for (auto &th : _threads)
        {
            //有多少线程就创建多少ThreadData类，并将每个线程的名字一一存储，以便后续使用
            ThreadData<T> *td = new ThreadData<T>(this, th->getname());
            //真正的创建出线程，在这里传入要执行的方法和对应的参数
            th->start(handTask, td);
        }
    }



    // 外部将任务放到线程池中
    void push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        for (auto &th : _threads)
        {
            delete th;
        }
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _num; // 线程的数量
    std::vector<Thread *> _threads;
    std::queue<T> _task_queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};